/**
 * Fix All File URLs Migration
 * Ensures all attachment and avatar URLs are universal and work regardless of ROOT_URL and PORT settings
 */

import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { ReactiveCache } from '/imports/reactiveCache';
import Boards from '/models/boards';
import Users from '/models/users';
import Attachments from '/models/attachments';
import Avatars from '/models/avatars';
import Cards from '/models/cards';
import { generateUniversalAttachmentUrl, generateUniversalAvatarUrl, cleanFileUrl, extractFileIdFromUrl, isUniversalFileUrl } from '/models/lib/universalUrlGenerator';

class FixAllFileUrlsMigration {
  constructor() {
    this.name = 'fixAllFileUrls';
    this.version = 1;
  }

  /**
   * Check if migration is needed for a board
   */
  needsMigration(boardId) {
    // Get all users who are members of this board
    const board = ReactiveCache.getBoard(boardId);
    if (!board || !board.members) {
      return false;
    }
    
    const memberIds = board.members.map(m => m.userId);
    
    // Check for problematic avatar URLs for board members
    const users = ReactiveCache.getUsers({ _id: { $in: memberIds } });
    for (const user of users) {
      if (user.profile && user.profile.avatarUrl) {
        const avatarUrl = user.profile.avatarUrl;
        if (this.hasProblematicUrl(avatarUrl)) {
          return true;
        }
      }
    }

    // Check for problematic attachment URLs on this board
    const cards = ReactiveCache.getCards({ boardId });
    const cardIds = cards.map(c => c._id);
    const attachments = ReactiveCache.getAttachments({ cardId: { $in: cardIds } });
    
    for (const attachment of attachments) {
      if (attachment.url && this.hasProblematicUrl(attachment.url)) {
        return true;
      }
    }

    return false;
  }

  /**
   * Check if a URL has problematic patterns
   */
  hasProblematicUrl(url) {
    if (!url) return false;
    
    // Check for auth parameters
    if (url.includes('auth=false') || url.includes('brokenIsFine=true')) {
      return true;
    }
    
    // Check for absolute URLs with domains
    if (url.startsWith('http://') || url.startsWith('https://')) {
      return true;
    }
    
    // Check for ROOT_URL dependencies
    if (Meteor.isServer && process.env.ROOT_URL) {
      try {
        const rootUrl = new URL(process.env.ROOT_URL);
        if (rootUrl.pathname && rootUrl.pathname !== '/' && url.includes(rootUrl.pathname)) {
          return true;
        }
      } catch (e) {
        // Ignore URL parsing errors
      }
    }
    
    // Check for non-universal file URLs
    if (url.includes('/cfs/files/') && !isUniversalFileUrl(url, 'attachment') && !isUniversalFileUrl(url, 'avatar')) {
      return true;
    }
    
    return false;
  }

  /**
   * Execute the migration for a board
   */
  async execute(boardId) {
    let filesFixed = 0;
    let errors = [];

    console.log(`Starting universal file URL migration for board ${boardId}...`);

    try {
      // Fix avatar URLs for board members
      const avatarFixed = await this.fixAvatarUrls(boardId);
      filesFixed += avatarFixed;

      // Fix attachment URLs for board cards
      const attachmentFixed = await this.fixAttachmentUrls(boardId);
      filesFixed += attachmentFixed;

      // Fix card attachment references
      const cardFixed = await this.fixCardAttachmentUrls(boardId);
      filesFixed += cardFixed;

    } catch (error) {
      console.error('Error during file URL migration for board', boardId, ':', error);
      errors.push(error.message);
    }

    console.log(`Universal file URL migration completed for board ${boardId}. Fixed ${filesFixed} file URLs.`);
    
    return {
      success: errors.length === 0,
      filesFixed,
      errors,
      changes: [`Fixed ${filesFixed} file URLs for this board`]
    };
  }

  /**
   * Fix avatar URLs in user profiles for board members
   */
  async fixAvatarUrls(boardId) {
    const board = ReactiveCache.getBoard(boardId);
    if (!board || !board.members) {
      return 0;
    }
    
    const memberIds = board.members.map(m => m.userId);
    const users = ReactiveCache.getUsers({ _id: { $in: memberIds } });
    let avatarsFixed = 0;

    for (const user of users) {
      if (user.profile && user.profile.avatarUrl) {
        const avatarUrl = user.profile.avatarUrl;
        
        if (this.hasProblematicUrl(avatarUrl)) {
          try {
            // Extract file ID from URL
            const fileId = extractFileIdFromUrl(avatarUrl, 'avatar');
            
            let cleanUrl;
            if (fileId) {
              // Generate universal URL
              cleanUrl = generateUniversalAvatarUrl(fileId);
            } else {
              // Clean existing URL
              cleanUrl = cleanFileUrl(avatarUrl, 'avatar');
            }
            
            if (cleanUrl && cleanUrl !== avatarUrl) {
              // Update user's avatar URL
              Users.update(user._id, {
                $set: {
                  'profile.avatarUrl': cleanUrl,
                  modifiedAt: new Date()
                }
              });
              
              avatarsFixed++;
              
              if (process.env.DEBUG === 'true') {
                console.log(`Fixed avatar URL for user ${user.username}: ${avatarUrl} -> ${cleanUrl}`);
              }
            }
          } catch (error) {
            console.error(`Error fixing avatar URL for user ${user.username}:`, error);
          }
        }
      }
    }

    return avatarsFixed;
  }

  /**
   * Fix attachment URLs in attachment records for this board
   */
  async fixAttachmentUrls(boardId) {
    const cards = ReactiveCache.getCards({ boardId });
    const cardIds = cards.map(c => c._id);
    const attachments = ReactiveCache.getAttachments({ cardId: { $in: cardIds } });
    let attachmentsFixed = 0;

    for (const attachment of attachments) {
      // Check if attachment has URL field that needs fixing
      if (attachment.url && this.hasProblematicUrl(attachment.url)) {
        try {
          const fileId = attachment._id;
          const cleanUrl = generateUniversalAttachmentUrl(fileId);
          
          if (cleanUrl && cleanUrl !== attachment.url) {
            // Update attachment URL
            Attachments.update(attachment._id, {
              $set: {
                url: cleanUrl,
                modifiedAt: new Date()
              }
            });
            
            attachmentsFixed++;
            
            if (process.env.DEBUG === 'true') {
              console.log(`Fixed attachment URL: ${attachment.url} -> ${cleanUrl}`);
            }
          }
        } catch (error) {
          console.error(`Error fixing attachment URL for ${attachment._id}:`, error);
        }
      }
    }

    return attachmentsFixed;
  }

  /**
   * Fix attachment URLs in the Attachments collection for this board
   */
  async fixCardAttachmentUrls(boardId) {
    const cards = ReactiveCache.getCards({ boardId });
    const cardIds = cards.map(c => c._id);
    const attachments = ReactiveCache.getAttachments({ cardId: { $in: cardIds } });
    let attachmentsFixed = 0;

    for (const attachment of attachments) {
      if (attachment.url && this.hasProblematicUrl(attachment.url)) {
        try {
          const fileId = attachment._id || extractFileIdFromUrl(attachment.url, 'attachment');
          const cleanUrl = fileId ? generateUniversalAttachmentUrl(fileId) : cleanFileUrl(attachment.url, 'attachment');
          
          if (cleanUrl && cleanUrl !== attachment.url) {
            // Update attachment with fixed URL
            Attachments.update(attachment._id, {
              $set: {
                url: cleanUrl,
                modifiedAt: new Date()
              }
            });
            
            attachmentsFixed++;
            
            if (process.env.DEBUG === 'true') {
              console.log(`Fixed attachment URL ${attachment._id}`);
            }
          }
        } catch (error) {
          console.error(`Error fixing attachment URL:`, error);
        }
      }
    }

    return attachmentsFixed;
  }
}

// Export singleton instance
export const fixAllFileUrlsMigration = new FixAllFileUrlsMigration();

// Meteor methods
Meteor.methods({
  'fixAllFileUrls.execute'(boardId) {
    check(boardId, String);
    
    if (!this.userId) {
      throw new Meteor.Error('not-authorized', 'You must be logged in');
    }

    // Check if user is board admin
    const board = ReactiveCache.getBoard(boardId);
    if (!board) {
      throw new Meteor.Error('board-not-found', 'Board not found');
    }

    const user = ReactiveCache.getUser(this.userId);
    if (!user) {
      throw new Meteor.Error('user-not-found', 'User not found');
    }

    // Only board admins can run migrations
    const isBoardAdmin = board.members && board.members.some(
      member => member.userId === this.userId && member.isAdmin
    );

    if (!isBoardAdmin && !user.isAdmin) {
      throw new Meteor.Error('not-authorized', 'Only board administrators can run migrations');
    }
    
    return fixAllFileUrlsMigration.execute(boardId);
  },

  'fixAllFileUrls.needsMigration'(boardId) {
    check(boardId, String);
    
    if (!this.userId) {
      throw new Meteor.Error('not-authorized', 'You must be logged in');
    }
    
    return fixAllFileUrlsMigration.needsMigration(boardId);
  }
});
